/***
 * * PROJECT
 * *    ATaG
 * * VERSION
 * *    $Revision: 1.4 $
 * * DATE
 * *    $Date: 2007/08/17 20:37:35 $
 * * LOG
 * *    $Log: NodeInfo.java,v $
 * *    Revision 1.4  2007/08/17 20:37:35  animesh
 * *    no message
 * *
 * *    Revision 1.3  2007/08/17 19:56:55  animesh
 * *    regionLabel and abilityString added
 * *
 * *    Revision 1.2  2007/06/09 07:15:52  animesh
 * *    update after fixing all but sets and serialization.
 * *
 * *    Revision 1.21  2007/01/29 18:44:37  lmottola
 * *    Refactored task assignment code.
 * *
 * *    Revision 1.20  2007/01/29 17:48:01  lmottola
 * *    Added debug info in toString() method.
 * *
 * *    Revision 1.19  2006/12/30 09:26:49  animesh
 * *    fixed minor typo.
 * *
 * *    Revision 1.18  2006/12/20 23:05:07  lmottola
 * *    Removed reference to ATaGProgram in NodeInfo.
 * *
 * *    Revision 1.17  2006/12/14 23:06:35  lmottola
 * *    Added constructor for compiler use.
 * *
 * *    Revision 1.16  2006/12/14 05:15:15  lmottola
 * *    Moved Estimator in atag.compiler and various cleanup.
 * *
 * *    Revision 1.15  2006/11/03 23:09:34  lmottola
 * *    Changed nodeAttributes package.
 * *
 * *    Revision 1.14  2006/11/03 23:08:17  lmottola
 * *    Traffic application beta running.
 * *
 * *    Revision 1.13  2006/10/30 23:53:56  animesh
 * *    added new function to return the value of the regionID.. perhaps this needs more work, as a node may have multiple regionIDs.
 * *
 * *    Revision 1.12  2006/10/27 01:28:28  lmottola
 * *    Debugging support added.
 * *
 * *    Revision 1.11  2006/10/27 00:11:58  lmottola
 * *    Automatic generation of attribute describing the tasks running on a node.
 * *
 * *    Revision 1.10  2006/10/25 22:50:49  lmottola
 * *    Startup file created.
 * *
 * *    Revision 1.9  2006/10/25 19:06:20  lmottola
 * *    Refactored myLocation().
 * *
 * *    Revision 1.8  2006/10/25 18:24:02  lmottola
 * *    Added getMyLocation() method.
 * *
 * *    Revision 1.7  2006/10/24 00:08:50  lmottola
 * *    Added sendingCost field.
 * *
 * *    Revision 1.6  2006/10/21 01:05:12  lmottola
 * *    Changed method getNodeAttributes.
 * *
 * *    Revision 1.5  2006/10/20 00:30:01  lmottola
 * *    Added constructor.
 * *
 * *    Revision 1.4  2006/10/20 00:27:15  lmottola
 * *    Made NodeAttribute abstract.
 * *
 * *    Revision 1.3  2006/10/19 21:49:22  lmottola
 * *    Added getAttributes method.
 * *
 * *    Revision 1.2  2006/10/19 21:21:52  lmottola
 * *    Added CVS preamble.
 * *
 * *
 * *   ATaG (Abstract Task Graph) - Data-driven Macroprogramming for
 * *                                Sensor Networks
 * *
 * *   This program is free software; you can redistribute it and/or
 * *   modify it under the terms of the GNU General Public License
 * *   as published by the Free Software Foundation; either version 2
 * *   of the License, or (at your option) any later version.
 * *
 * *   This program is distributed in the hope that it will be useful,
 * *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * *   GNU General Public License for more details.
 * *
 * *   You should have received a copy of the GNU General Public License
 * *   along with this program; if not, you may find a copy at the FSF web
 * *   site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
 * *   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * *   Boston, MA  02111-1307, USA
 ***/

package atag.runtime;

//import java.util.Collection;
//import java.util.Iterator;
//import java.util.List;
//import java.util.Set;
import java.util.Vector;

import atag.runtime.ln.nodeAttributes.IntegerAttribute;
import atag.runtime.ln.nodeAttributes.NodeAttribute;
import atag.runtime.ln.nodeAttributes.StringSetAttribute;

public class NodeInfo {

	private Vector attributes;

	private Vector assignedTasks;

	private int myId;

	private NodeLocation myLocation;

	private int sendingCost;

	private IClock clock;

        private String regionLabel;
        
        private String abilityString; 
        //to store the ability string from the topology file. 
        //Used when creating the startup files

        public static final String ASSIGNED_TASK_ATTR_NAME = "runningTasks";
        
        // Indicates invalid/unknown Region Identifier for mobile nodes
        public static final int REGION_ID_INVALID = -1;
        
        //Denotes that the IP will be assigned dynamically or is not known
        public static final String PHYSICAL_ADDR_IP_DYNAMIC="0.0.0.0";
        
	// For compiler use 
	//public NodeInfo(int myId, NodeLocation myLocation, Collection nodeAttributes) {
	public NodeInfo(int myId, NodeLocation myLocation, Vector nodeAttributes) {
		
		//attributes = new Vector(nodeAttributes);
                this.attributes = new Vector();
                for(int i=0; i<nodeAttributes.size(); i++){
                    this.attributes.addElement(nodeAttributes.elementAt(i));
                }
                this.myId = myId;
		this.myLocation = myLocation;
		this.assignedTasks = new Vector();
                this.regionLabel = "";
                this.abilityString = "";
	}

//	public void assignTasks(Set tasks) {
	public void assignTasks(Vector tasks) {

		//this.assignedTasks = new Vector(tasks);
                this.assignedTasks = new Vector();
                for(int i=0; i< tasks.size(); i++){
                    this.assignedTasks.addElement(tasks.elementAt(i));
                }

		// Remove any previously assignedTask attribute
		//Iterator it = attributes.iterator();
		
                //fill this vector with attributes to be removed
                NodeAttribute remAttr = null;
                
                for(int ai=0; ai<attributes.size(); ai++ ) {
			NodeAttribute attr = (NodeAttribute) attributes.elementAt(ai);
			if (attr.getKey().equals(ASSIGNED_TASK_ATTR_NAME)) {
//				attributes.remove(attr);
                		remAttr = attr;
				break;
			}
		}
                
                if (remAttr != null)
                        this.attributes.removeElement(remAttr);

		attributes.addElement(new StringSetAttribute(ASSIGNED_TASK_ATTR_NAME, AdapterVectortoString(assignedTasks)));
	}
    //added on 29 May to comply with new protocol
    String[] AdapterVectortoString(Vector assignedTasks)
    {

        String[] string = new String[assignedTasks.size()];
        for(int i=0;i<assignedTasks.size();i++)
            string[i]=(String)assignedTasks.elementAt(i);
        return string;
    }

	// For runtime use
//	public NodeInfo(int myId, NodeLocation myLocation,
//			Collection nodeAttributes, int sendingCost, List assignedTasks, IClock clock) {
	public NodeInfo(int myId, NodeLocation myLocation,
			Vector nodeAttributes, int sendingCost, Vector assignedTasks, IClock clock) {
		
		attributes = new Vector(nodeAttributes.size());
                
                for(int i=0; i<nodeAttributes.size(); i++)
                    attributes.addElement(nodeAttributes.elementAt(i));
                
		this.sendingCost = sendingCost;
		this.myId = myId;
		this.myLocation = myLocation;
		this.clock = clock;
		this.assignedTasks = new Vector(assignedTasks.size());
                for(int ai=0; ai<assignedTasks.size(); ai++){
                    this.assignedTasks.addElement(assignedTasks.elementAt(ai));
                }

		// Automatic generation of attributes - assigned atsks
		attributes.addElement(new StringSetAttribute(ASSIGNED_TASK_ATTR_NAME, AdapterVectortoString(assignedTasks)));

		// TODO: Generate an attribute for location
                this.regionLabel = "";
                this.abilityString = "";
	}

	public void addNodeAttribute(NodeAttribute attr) {
		attributes.addElement(attr);
	}

//	public Collection getNodeAttributes() {
	public Vector getNodeAttributes() {
		return attributes;
	}

	public Object getAttributeByName(String name) {

		//Iterator it = attributes.iterator();
		for (int ai=0 ; ai< attributes.size(); ai++) {
			NodeAttribute attr = (NodeAttribute) attributes.elementAt(ai);
			if (attr.getKey().equals(name)) {
				return attr.getValue();
			}
		}
		return null;
	}

	public synchronized void setRegionAttribute(int regionID) {
		//Iterator it = attributes.iterator();
		for (int ai=0 ; ai< attributes.size(); ai++) {
			NodeAttribute attr = (NodeAttribute) attributes.elementAt(ai);
			if (attr.getKey().equals(regionLabel)) {				
				IntegerAttribute regionAttr = new IntegerAttribute(regionLabel, regionID);
				//attributes.set(ai,regionAttr);
				attributes.setElementAt(regionAttr,ai); // J2ME compliant
			}		
		}		
	}

	public int getMyId() {
		return myId;
	}

	public NodeLocation getMyLocation() {
		return this.myLocation;
	}

	public boolean isTaskAssigned(int taskID) {
		return assignedTasks.contains(String.valueOf(taskID));
	}

	public int getSendingCost() {
		return sendingCost;
	}

	public IClock getClock() {
		return clock;
	}

	public void debugPrint(String debugMessage) {
		System.out.println(myId + ": " + debugMessage + " at time "
				+ clock.getTime() + " " + clock.getDate());
		System.out.flush();
	}

    public String toString() {
    	
    	String ret = "NodeInfo id: "+myId;
    	
//    	Iterator it = attributes.iterator();
    	for(int ai=0; ai<attributes.size(); ai++) {
    		ret = ret.concat("\nAttribute "+ ((NodeAttribute)attributes.elementAt(ai)).toString());
    	}
    	
    	return ret;
    }
    public void setRegionLabel(String newRegionLabel) {
        this.regionLabel = newRegionLabel;
    }
    
    public String getRegionLabel(){
        return this.regionLabel;
    }
    
    public void setAbilityString(String newAbilityString){
        this.abilityString = newAbilityString;
    }
    
    public String getAbilityString(){
        return this.abilityString;
    }
}
